home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
comm
/
misc
/
zedzap05.lha
/
zm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-26
|
19KB
|
765 lines
/**********************************************************************
* Z M . C
* ZMODEM protocol primitives
* 01-19-87 Chuck Forsberg Omen Technology Inc
*
* 29 July 89:
* Major overhaul by Rick Huebner for adaptation to Amiga XPR protocol spec
*
* 28 October 89:
* Converted to Lattice C 5.04
*
* 15 November 1991
* Code added to support CRC-32 by William M. Perkins.
**********************************************************************/
#include <proto/all.h>
#include <exec/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "xproto.h"
#include "zmodem.h"
#include "xprzmodem.h"
#include "zcrc.h"
struct ExecBase *SysBase = (struct ExecBase*)4l;
static char *frametypes[] =
{
"Carrier Lost", /* -3 */
"TIMEOUT", /* -2 */
"ERROR", /* -1 */
#define FTOFFSET 3
"ZRQINIT",
"ZRINIT",
"ZSINIT",
"ZACK",
"ZFILE",
"ZSKIP",
"ZNAK",
"ZABORT",
"ZFIN",
"ZRPOS",
"ZDATA",
"ZEOF",
"ZFERR",
"ZCRC",
"ZCHALLENGE",
"ZCOMPL",
"ZCAN",
"ZFREECNT",
"ZCOMMAND",
"ZSTDERR",
"xxxxx"
#define FRTYPES 22 /* Total number of frame types in this array */
/* not including psuedo negative entries */
};
static UBYTE DLE_actions[] =
{
0,0,0,0,0,0,0,0, 0,0,0,0,0,2,0,0, 1,1,0,1,0,0,0,0, 1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,2,0,0, 1,1,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
};
char ProtocolInfo[] = {
"XprZedZap.Library By Yves Konigshofer\r\n",
"\r\n"
"Original ZModem Protocol Primitives: Chuck Forsberg (Omen Technology Inc.)\r\n",
" Adaptation To Amiga XPR Protocol: Rick Huebner\r\n",
" Addition Of CRC-32 Routines: William M. Perkins\r\n",
" Combining Of v2.10 And v2.5x: Yves Konigshofer\r\n",
" ZedZap Additions: Yves Konigshofer\r\n",
"\r\n",
"This Library IS Public Domain...\r\n"
};
/**********************************************************
* void zsbhdr(struct Vars *v, USHORT type)
*
* Send ZMODEM binary header hdr of type type
**********************************************************/
void zsbhdr(struct Vars *v, USHORT type)
{
UBYTE *hdr = v->Txhdr;
short n;
USHORT crc;
ULONG crc32;
xsendline(v, ZPAD);
xsendline(v, ZDLE);
if (v->Crc32t = v->Txfcs32) /* zsbh32() */
{
xsendline(v, ZBIN32);
zsendline(v, (UBYTE) type);
crc32 = 0xFFFFFFFFL;
crc32 = UPDC32(type, crc32);
for (n = 4; --n >= 0; ++hdr)
{
crc32 = UPDC32((0377 & *hdr), crc32);
zsendline(v, *hdr);
}
crc32 = ~crc32;
for (n = 4; --n >= 0;)
{
zsendline(v, (int) crc32);
crc32 >>= 8;
}
}
else
{
xsendline(v, ZBIN);
zsendline(v, (UBYTE) type);
crc = updcrc(type, 0);
for (n = 4; --n >= 0; )
{
zsendline(v, *hdr);
crc = updcrc(((USHORT) (*hdr++)), crc);
}
crc = updcrc(((USHORT) 0), crc);
crc = updcrc(((USHORT) 0), crc);
zsendline(v, (UBYTE) (crc >> 8));
zsendline(v, (UBYTE) crc);
}
} /* End of void zsbhdr() */
/**********************************************************
* void zshhdr(struct Vars *v, USHORT type)
*
* Send ZMODEM HEX header hdr of type type
**********************************************************/
void zshhdr(struct Vars *v, USHORT type)
{
UBYTE *hdr = v->Txhdr;
short n;
USHORT crc;
sendline(v, ZPAD);
sendline(v, ZPAD);
sendline(v, ZDLE);
sendline(v, ZHEX);
zputhex(v, (UBYTE) type);
v->Crc32t = 0;
crc = updcrc(type, 0);
for (n = 4; --n >= 0; )
{
zputhex(v, *hdr);
crc = updcrc(((USHORT) (*hdr++)), crc);
}
crc = updcrc(((USHORT) 0), crc);
crc = updcrc(((USHORT) 0), crc);
zputhex(v, (UBYTE) (crc >> 8));
zputhex(v, (UBYTE) crc);
/* Make it printable on remote machine */
sendline(v, '\r');
sendline(v, '\n');
/* Uncork the remote in case a fake XOFF has stopped data flow */
if (type != ZFIN)
sendline(v, XON);
} /* End of void zshhdr() */
/**********************************************************
* void zsdata() and void zsda32()
*
* Send binary array buf of length length, with ending
* ZDLE sequence frameend
**********************************************************/
void zsdata(struct Vars *v, short length, USHORT frameend)
{
UBYTE *buf, *outptr, c;
USHORT crc;
ULONG crc32;
buf = v->Pktbuf;
outptr = v->Outbuf + v->Outbuflen;
crc32 = 0xFFFFFFFFL; /* zsda32() */
crc = 0;
while (--length >= 0)
{
switch (DLE_actions[c = *buf])
{
case 2:
if (v->Lastzsent != '@')
goto sendit;
/* Fallthrough */
case 1:
*outptr++ = ZDLE;
c ^= 0x40;
sendit:
case 0:
*outptr++ = v->Lastzsent = c;
}
if (v->Crc32t) /* zsda32() */
crc32 = UPDC32((0xFF & *buf++), crc32);
else
crc = updcrc(((USHORT) (*buf++)), crc);
}
*outptr++ = ZDLE;
*outptr++ = frameend;
v->Outbuflen = outptr - v->Outbuf;
if (v->Crc32t) /* zsda32() */
{
crc32 = UPDC32(frameend, crc32);
crc32 = ~crc32;
for (length = 4; --length >= 0; )
{
zsendline(v, (int) crc32);
crc32 >>= 8;
}
}
else
{
crc = updcrc(frameend, crc);
crc = updcrc(((USHORT) 0), crc);
crc = updcrc(((USHORT) 0), crc);
zsendline(v, (UBYTE) (crc >> 8));
zsendline(v, (UBYTE) crc);
}
if (frameend == ZCRCW)
xsendline(v, XON);
} /* End of void zsdata() */
/**********************************************************
* short zrdata(struct Vars *v, UBYTE *buf, short length)
*
* Receive array buf of max length with ending ZDLE sequence
* and CRC-16. Returns the ending character or error code.
**********************************************************/
short zrdata(struct Vars *v, UBYTE *buf, short length)
{
short c, d;
USHORT crc;
if (v->Rxframeind == ZBIN32)
return zrdat32(v, buf, length);
crc = v->Rxcount = 0;
for (;;)
{
if ((c = zdlread(v)) & ~0xFF)
{
crcfoo:
switch (c)
{
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
crc = updcrc(((d = c) & 0xFF), crc);
if ((c = zdlread(v)) & ~0xFF)
goto crcfoo;
crc = updcrc(c, crc);
if ((c = zdlread(v)) & ~0xFF)
goto crcfoo;
crc = updcrc(c, crc);
if (crc & 0xFFFF)
{
strcpy(v->Msgbuf, "Bad Data Packet CRC-16 ");
return ERROR;
}
return d;
case GOTCAN:
strcpy(v->Msgbuf, "Transfer Cancelled (Remote Sent ZCAN)");
return ZCAN;
case TIMEOUT:
strcpy(v->Msgbuf, "Data Packet Timeout ");
return c;
case RCDO:
strcpy(v->Msgbuf, "Transfer Cancelled (Remote Dropped Carrier)");
return c;
default:
strcpy(v->Msgbuf, "Unrecognizable Data Packet ");
return c;
}
}
if (--length < 0)
{
strcpy(v->Msgbuf, "Data Packet Too Long ");
return ERROR;
}
++v->Rxcount;
*buf++ = c;
crc = updcrc(c, crc);
continue;
}
} /* End of short zrdata() */
/**********************************************************
* short zrdat32(struct Vars *v, UBYTE *buf, short length)
*
* Receive array buf of max length with ending ZDLE sequence
* and CRC-32. Returns the ending character or error code.
**********************************************************/
short zrdat32(struct Vars *v, UBYTE *buf, short length)
{
short c, d;
ULONG crc32;
crc32 = 0xFFFFFFFFL;
v->Rxcount = 0;
for (;;)
{
if ((c = zdlread(v)) & ~0xFF)
{
crcfoo:
switch (c)
{
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
d = c;
c &= 0xFF;
crc32 = UPDC32(c, crc32);
if ((c = zdlread(v)) & ~0xFF)
goto crcfoo;
crc32 = UPDC32(c, crc32);
if ((c = zdlread(v)) & ~0xFF)
goto crcfoo;
crc32 = UPDC32(c, crc32);
if ((c = zdlread(v)) & ~0xFF)
goto crcfoo;
crc32 = UPDC32(c, crc32);
if ((c = zdlread(v)) & ~0xFF)
goto crcfoo;
crc32 = UPDC32(c, crc32);
if (crc32 != 0xDEBB20E3)
{
strcpy(v->Msgbuf, "Bad Data Packet CRC-32 ");
return ERROR;
}
return d;
case GOTCAN:
strcpy(v->Msgbuf, "Transfer Cancelled (Remote Sent ZCAN)");
return ZCAN;
case TIMEOUT:
strcpy(v->Msgbuf, "Data Packet Timeout ");
return c;
case RCDO:
strcpy(v->Msgbuf, "Transfer Cancelled (Remote Dropped Carrier)");
return c;
default:
strcpy(v->Msgbuf, "Unrecognizable Data Packet ");
return c;
}
}
if (--length < 0)
{
strcpy(v->Msgbuf, "Data Packet Too Long ");
return ERROR;
}
++v->Rxcount;
*buf++ = c;
crc32 = UPDC32(c, crc32);
continue;
}
} /* End of short zrdat32() */
/**********************************************************
* short zgethdr(struct Vars *v)
*
* Read a ZMODEM header to hdr, either binary or hex.
* On success return type of header.
* Otherwise return negative on error.
**********************************************************/
short zgethdr(struct Vars *v)
{
short c, cancount;
long n;
#ifdef DEBUGLOG
UBYTE msgbuf [128];
#endif
/* n = v->Baud; */ /* Max characters before start of frame */
n = v->KSIZE * 2;/* We assume that since extra data may be generated */
/* or lost due to line noise, that the maximum data */
/* to the next header will be less than 8129 bytes. */
/* Due to the fact that the Amiga's serial port can */
/* loose data and thereby fall into the next header */
/* this should allow another header to be found! */
cancount = 5;
again:
v->Rxframeind = v->Rxtype = 0;
switch (c = noxrd7(v))
{
case RCDO:
case TIMEOUT:
goto fifi;
case CAN:
if (--cancount <= 0)
{
c = ZCAN;
goto fifi;
}
default:
agn2:
if (--n <= 0)
{
strcpy(v->Msgbuf, "Header Search Garbage Count Exceeded ");
return ERROR;
}
if (c != CAN)
cancount = 5;
goto again;
case ZPAD: /* This is what we want. */
break;
}
cancount = 5;
splat:
switch (c = noxrd7(v))
{
case ZPAD:
goto splat;
case RCDO:
case TIMEOUT:
goto fifi;
default:
goto agn2;
case ZDLE: /* This is what we want. */
break;
}
switch (c = noxrd7(v))
{
case RCDO:
case TIMEOUT:
goto fifi;
case ZBIN:
v->Rxframeind = ZBIN;
v->Crc32 = FALSE;
c = zrbhdr(v);
break;
case ZBIN32:
v->Crc32 = v->Rxframeind = ZBIN32;
c = zrbhdr32(v);
break;
case ZHEX:
v->Rxframeind = ZHEX;
v->Crc32 = FALSE;
c = zrhhdr(v);
break;
case CAN:
if (--cancount <= 0)
{
c = ZCAN;
goto fifi;
}
goto agn2;
default:
goto agn2;
}
v->Rxpos = rclhdr(v);
fifi:
switch (c)
{
case GOTCAN:
c = ZCAN;
case ZNAK:
case ZCAN:
case ERROR:
case TIMEOUT:
case RCDO:
sprintf(v->Msgbuf, "%s %s ", frametypes[c + FTOFFSET],
(c >= 0) ? "header" : "error");
}
return c;
} /* End of short zgethdr() */
/**********************************************************
* short zrbhdr(struct Vars *v)
*
* Receive a binary style header (type and position)
**********************************************************/
short zrbhdr(struct Vars *v)
{
UBYTE *hdr = v->Rxhdr;
short c, n;
USHORT crc;
if ((c = zdlread(v)) & ~0xFF)
return c;
v->Rxtype = c;
crc = updcrc(c, 0);
for (n = 4; --n >= 0; )
{
if ((c = zdlread(v)) & ~0xFF)
return c;
crc = updcrc(c, crc);
*hdr++ = c;
}
if ((c = zdlread(v)) & ~0xFF)
return c;
crc = updcrc(c, crc);
if ((c = zdlread(v)) & ~0xFF)
return c;
crc = updcrc(c, crc);
if (crc & 0xFFFF)
{
strcpy(v->Msgbuf, "Bad Header CRC-16 ");
return ERROR;
}
return v->Rxtype;
} /* End of short zrbhdr() */
/**********************************************************
* short zrbhdr32(struct Vars *v)
*
* Receive a binary style header (type and position) with
* 32 bit FCS
**********************************************************/
short zrbhdr32(struct Vars *v)
{
UBYTE *hdr = v->Rxhdr;
short c, n;
ULONG crc32;
if ((c = zdlread(v)) & ~0xFF)
return c;
v->Rxtype = c;
crc32 = 0xFFFFFFFFL;
crc32 = UPDC32(c, crc32);
for (n = 4; --n >= 0; )
{
if ((c = zdlread(v)) & ~0xFF)
return c;
crc32 = UPDC32(c, crc32);
*hdr++ = c;
}
for (n = 4; --n >= 0; )
{
if ((c = zdlread(v)) & ~0xFF)
return c;
crc32 = UPDC32(c, crc32);
}
if (crc32 != 0xDEBB20E3)
{
strcpy(v->Msgbuf, "Bad Header CRC-32 ");
return ERROR;
}
return v->Rxtype;
} /* End of short zrbhdr32() */
/**********************************************************
* short zrhhdr(struct Vars *v)
*
* Receive a hex style header (type and position)
**********************************************************/
short zrhhdr(struct Vars *v)
{
UBYTE *hdr = v->Rxhdr;
short c, n;
USHORT crc;
if ((c = zgethex(v)) < 0)
return c;
v->Rxtype = c;
crc = updcrc(c, 0);
for (n = 4; --n >= 0; )
{
if ((c = zgethex(v)) < 0)
return c;
crc = updcrc(c, crc);
*hdr++ = c;
}
if ((c = zgethex(v)) < 0)
return c;
crc = updcrc(c, crc);
if ((c = zgethex(v)) < 0)
return c;
crc = updcrc(c, crc);
if (crc & 0xFFFF)
{
strcpy(v->Msgbuf, "Bad Header CRC ");
return ERROR;
}
if (readock(v, 1) == '\r')
readock(v, 1); /* Throw away possible cr/lf */
return v->Rxtype;
} /* End of short zrhhdr() */
/**********************************************************
* void zputhex(struct Vars *v, UBYTE c)
*
* Send a byte as two hex digits
**********************************************************/
void zputhex(struct Vars *v, UBYTE c)
{
static char digits[] = "0123456789abcdef";
sendline(v, digits[(c >> 4) & 0x0F]);
sendline(v, digits[c & 0x0F]);
} /* End of void zputhex() */
/**********************************************************
* void zsendline(struct Vars *v, UBYTE c)
*
* Send character c with ZMODEM escape sequence encoding.
* Escape ZDLE, real DLE, XON, XOFF, and CR following @ (Telenet net escape)
**********************************************************/
void zsendline(struct Vars *v, UBYTE c)
{
switch (DLE_actions[c])
{
case 2:
if (v->Lastzsent != '@')
goto sendit;
/* Fallthrough */
case 1:
xsendline(v, ZDLE);
c ^= 0x40;
sendit:
case 0:
xsendline(v, v->Lastzsent = c);
}
} /* End of void zsendline() */
/**********************************************************
* short zgethex(struct Vars *v)
*
* Decode two lower case hex digits into an 8 bit byte value
**********************************************************/
short zgethex(struct Vars *v)
{
short c, n;
if ((n = noxrd7(v)) < 0)
return n;
n -= '0';
if (n > 9)
n -= ('a' - ':');
if (n & ~0xF)
return ERROR;
if ((c = noxrd7(v)) < 0)
return c;
c -= '0';
if (c > 9)
c -= ('a' - ':');
if (c & ~0xF)
return ERROR;
return (short) (n << 4 | c);
} /* End of short zgethex() */
/**********************************************************
* short zdlread(struct Vars *v)
*
* Read a byte, checking for ZMODEM escape encoding
* including CAN*5 which represents a quick abort.
**********************************************************/
short zdlread(struct Vars *v)
{
short c;
if ((c = readock(v, v->Rxtimeout)) != ZDLE)
return c;
if ((c = readock(v, v->Rxtimeout)) < 0)
return c;
if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
return c;
if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
return c;
if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
return c;
switch (c)
{
case CAN:
return GOTCAN;
case ZCRCE:
case ZCRCG:
case ZCRCQ:
case ZCRCW:
return (short) (c | GOTOR);
case ZRUB0:
return 0x7F;
case ZRUB1:
return 0xFF;
default:
if ((c & 0x60) == 0x40)
return (short) (c ^ 0x40);
break;
}
strcpy(v->Msgbuf, "Bad ZedZap Escape Sequence ");
return ERROR;
} /* End of short zdlread() */
/**********************************************************
* short noxrd7(struct Vars *v)
*
* Read a character from the modem line with timeout.
* Eat parity, XON and XOFF characters.
**********************************************************/
short noxrd7(struct Vars *v)
{
short c;
for (;;)
{
if ((c = readock(v, v->Rxtimeout)) < 0)
return c;
switch (c &= 0x7F)
{
case XON:
case XOFF:
continue;
default:
return c;
}
}
} /* short noxrd7() */
/**********************************************************
* void stohdr(struct Vars *v, long pos)
*
* Store long integer pos in Txhdr
**********************************************************/
void stohdr(struct Vars *v, long pos)
{
v->Txhdr[ZP0] = pos;
pos >>= 8;
v->Txhdr[ZP1] = pos;
pos >>= 8;
v->Txhdr[ZP2] = pos;
pos >>= 8;
v->Txhdr[ZP3] = pos;
} /* End of void stohdr() */
/**********************************************************
* long rclhdr(struct Vars *v)
*
* Recover a long integer from a header
**********************************************************/
long rclhdr(struct Vars *v)
{
long l;
l = v->Rxhdr[ZP3];
l = (l << 8) | v->Rxhdr[ZP2];
l = (l << 8) | v->Rxhdr[ZP1];
l = (l << 8) | v->Rxhdr[ZP0];
return l;
} /* End of long rclhdr() */
/* End of Zm.c source */